#include "lock.h"
#include "sched.h"
#include "syscall.h"

/* used to fetch kernel_state error */
//uint64_t *error = (uint64_t *)0x123456;

void spin_lock_init(spin_lock_t *lock)
{
    lock->status = UNLOCKED;
}

void spin_lock_acquire(spin_lock_t *lock)
{
    while (LOCKED == lock->status)
    {
    };
    lock->status = LOCKED;
}

void spin_lock_release(spin_lock_t *lock)
{
    lock->status = UNLOCKED;
}

void do_mutex_lock_init(mutex_lock_t *lock)
{
    lock->status = UNLOCKED;
    queue_init(&(lock->mutex_lock_queue));
}

void do_mutex_lock_acquire(mutex_lock_t *lock)
{
    if (current_running->kernel_state == 1)
    {
        // while the lock is used, current task block
        while (lock->status == LOCKED)
        {
            do_block(&(lock->mutex_lock_queue));
        }
        lock->status = LOCKED;
    
        current_running->lock[lock->lock_id] = 1;
        current_running->lock_num++;
    }
    else
    {
        *error = 0;
    }
}

void do_mutex_lock_release(mutex_lock_t *lock)
{
    if (current_running->kernel_state == 1)
    {
        int i = 0;
        
        current_running->lock[lock->lock_id] = 0;
        current_running->lock_num--;
        
        lock->status = UNLOCKED;
        do_unblock_all(&lock->mutex_lock_queue);
    }
    else
    {
        *error = 0;
    }
}

int do_binsemget(int key)
{
    int lock_id;
    lock_id = key % LOCK_TOTAL_NUM;
    return lock_id;
}

void do_binsemop(int binsem_id, int op)
{
    if (op == BINSEM_OP_LOCK)
    {
        do_mutex_lock_acquire(&Lock[binsem_id]);
    }
    else if (op == BINSEM_OP_UNLOCK)
    {
        do_mutex_lock_release(&Lock[binsem_id]);
    }
    else
        ;
}